﻿#include "CyUSBdeviceManger.h"

CyUSBDeviceManger::CyUSBDeviceManger(QWidget *parent)
    : QWidget(parent),m_CurrentOpen(-1), m_HDevNotification(nullptr)
{
    // 获取当前窗口在windows系统中的句柄
    m_Hwnd = reinterpret_cast<HWND>(this->winId());
    m_CyUsbDevice = new CCyUSBDevice(m_Hwnd, CYUSBDRV_GUID, true);
    this->RegisterDeviceInterface();
}

void CyUSBDeviceManger::RegisterDeviceInterface()
{
        if (m_HDevNotification == nullptr ) m_HDevNotification = new HDEVNOTIFY;
        // 设置设备广播过滤器(设置我所关心的设备GUID)
        DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
        ZeroMemory(&NotificationFilter, sizeof(NotificationFilter));
        NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
        NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
        NotificationFilter.dbcc_classguid = CYUSBDRV_GUID;

        // 注册设备通知
        *m_HDevNotification = RegisterDeviceNotification(
            NULL,                   // (这里不设置通知窗口,因为前面已经设置过了)
            &NotificationFilter,
            DEVICE_NOTIFY_WINDOW_HANDLE
        );

        if (!m_HDevNotification)
        {
            qDebug() << "注册设备通知失败，错误码：" << GetLastError();
        }
        else
        {
            qDebug() << "成功注册设备通知。";
        }
}

bool CyUSBDeviceManger::nativeEvent(const QByteArray &eventType, void *message, long *result)
{
     MSG* msg = static_cast<MSG*>(message);
     // 用于接收windows发送的消息
     // 每次接收到消息后都得重新new一次不然不会刷新连接设备
    if(eventType == "windows_generic_MSG" && msg->message == WM_DEVICECHANGE)
    {
        CCyUSBDevice* CyUsbDevice = new CCyUSBDevice;
        // 如果是windows的消息
        if(msg->message == WM_DEVICECHANGE && msg->wParam == DBT_DEVICEARRIVAL)
        {
            qDebug() << "接收到设备插入信息";
            // 设备通知的消息且是有新设备连入
            if(DeviceInsert(CyUsbDevice))
            {
                // 更改成功发送修改前端信号
                qDebug() << "发送设备插入信息, 当前插入电脑设备数量: " << m_USBVector.size();
                emit RefreshUSBDevice(DeviceStatus::In, &m_USBVector);
            }else return QWidget::nativeEvent(eventType, message, result);
        }else if(msg->message == WM_DEVICECHANGE && msg->wParam == DBT_DEVICEREMOVECOMPLETE)
        {
            qDebug() << "接收到设备拔出信息";
            if(DeviceInsert(CyUsbDevice))
            {
                if(m_CurrentOpen != -1)
                {
                    // 获取当前打开设备的名称(如果后面监测到拔出的设备就是当前打开的设备则关闭当前设备)
                    QString CurrentDeviceName = m_USBVector[m_CurrentOpen].m_DeviceName;
                    bool isIn = false;
                    for(int i = 0; i < m_USBVector.size(); i++)
                    {
                        if(CurrentDeviceName == m_USBVector[i].m_DeviceName) {
                            isIn = true;
                            break;
                        }
                    }
                    if(isIn == false)  {
                        m_CurrentOpen = -1;
                    }
                }

                // 更改成功发送修改前端信号
                emit RefreshUSBDevice(DeviceStatus::Out, &m_USBVector);
            }else return QWidget::nativeEvent(eventType, message, result);
        }
        CyUsbDevice->Close();
    }
    return QWidget::nativeEvent(eventType, message, result);
}

const QVector<USBDevice> *CyUSBDeviceManger::RUSBVectorP()
{
    return &m_USBVector;
}

bool CyUSBDeviceManger::CurrentOpen(ParameterKind kind, int *currentI)
{
    if(currentI == nullptr) return false;
    switch(kind)
    {
    case ParameterKind::Get:
        *currentI = m_CurrentOpen;
        break;
    case ParameterKind::Set:
        if(*currentI < 0) return false;
        m_CurrentOpen = *currentI;
        break;
    }

    return true;
}

bool CyUSBDeviceManger::DeviceInsert(CCyUSBDevice* PusbDevice)
{
    if(PusbDevice == nullptr) return false;

    QVector<USBDevice> tmpUSBDeviceV;                   // 临时的数据管理Vecotr容器(后面使用右值引用转换掉)
    USBDevice tmpDeviceInfo;                            // 用作临时存储设备信息
    int nDeviceCount = PusbDevice->DeviceCount();       // 获取当前连入电脑设备数量
    int nEndPointCount;                                 // 端点个数
    CCyUSBEndPoint* ptmpUSBEndPoint;                    // 用于表示端点对象句柄
    qDebug() << "开始Open";
    for(int i = 0; i < nDeviceCount; ++i)
    {
        try {
            if(!PusbDevice->Open(i))
            {
                // 打开失败
                qDebug() << "CyUSBDeviceManger::DeviceInsert  OPen失败";
                return false;
            }
        } catch (const char* e) {
                qDebug() << "CyUSBDeviceManger::DeviceInsert捕获异常: " << e;
                return false;
        }
        qDebug() << "Open成功";
        tmpDeviceInfo.m_DeviceName = QString("%1").arg(PusbDevice->DeviceName);
        tmpDeviceInfo.m_VendorID = PusbDevice->VendorID;
        tmpDeviceInfo.m_ProductID = PusbDevice->ProductID;
        tmpDeviceInfo.m_FriendlyName = QString("%1").arg(PusbDevice->FriendlyName);
        nEndPointCount = PusbDevice->EndPointCount();
        for(int j = 0; j < nEndPointCount; ++j)
        {
            ptmpUSBEndPoint = PusbDevice->EndPoints[j];
            if(ptmpUSBEndPoint->Attributes == 0x2 && ptmpUSBEndPoint->bIn)
            {
                // 当前是输入端点
                tmpDeviceInfo.m_InAddress = ptmpUSBEndPoint->Address;
            }else if(ptmpUSBEndPoint->Attributes == 0x2 && !ptmpUSBEndPoint->bIn)
            {
                // 当前是输出端点
                tmpDeviceInfo.m_OutAddress = ptmpUSBEndPoint->Address;
            }else if(ptmpUSBEndPoint->Attributes == 0)
            {
                // 当前是控制端点
                tmpDeviceInfo.m_ControlAddress = ptmpUSBEndPoint->Address;
            }
        }
        PusbDevice->Close();
        tmpUSBDeviceV.append(tmpDeviceInfo);
        }
    // 使用右值拷贝(减少拷贝次数)
    m_USBVector = std::move(tmpUSBDeviceV);
    return true;
}

int CyUSBDeviceManger::NameToIndex(QString DeviceName)
{
    auto it = std::find_if(m_USBVector.begin(), m_USBVector.end(), [=](const USBDevice& tmp){
            return tmp.m_DeviceName == DeviceName;
    });

    if(it != m_USBVector.end())
    {
        // 此时找到
        return it - m_USBVector.begin();
    }
    return -1;
}

USBDevice *CyUSBDeviceManger::NameToClass(QString DeviceName)
{
    auto it = std::find_if(m_USBVector.begin(), m_USBVector.end(), [=](const USBDevice& tmp){
            return tmp.m_DeviceName == DeviceName;
    });
    if(it != m_USBVector.end()) return it;
    return nullptr;
}

bool CyUSBDeviceManger::CheckDeviceCon()
{
    qDebug() << "当前连入设备数有: " << m_CyUsbDevice->DeviceCount();
    if (m_CyUsbDevice->DeviceCount() > 0)
    {
        if (this->DeviceInsert(m_CyUsbDevice)) {
            qDebug() << "发送刷新信号: " << m_USBVector.size();
            emit RefreshUSBDevice(DeviceStatus::In, &m_USBVector);
        }
    }
    return true;
}
